package screenpac.controllers;

import java.awt.Color;
import java.util.LinkedList;

import screenpac.extract.Constants;
import screenpac.features.GaiAStarSearch;
import screenpac.features.GaiNearFarPillDistance;
import screenpac.features.GaiRandomPill;
import screenpac.features.Utilities;
import screenpac.model.GameStateInterface;
import screenpac.model.GhostState;
import screenpac.model.Node;

public class GaiAstarStateAgent implements AgentInterface, Constants {

    /*
    This simple pill eater just heads for the nearest pill each time
     */
    GaiNearFarPillDistance nearFarPill;
    GaiRandomPill randPill;
    GaiAStarSearch aSearch;
    int ghostPathScore[];
    boolean needTarget;
    Node next = null;
    Node target;
    Node current;
    GameStateInterface gs;
    public enum State {NEAR_PILL, FAR_PILL, POWER_PILL, CHASE_GHOST, RAND_PILL};
    State currentState;
   
    public GaiAstarStateAgent() {
        nearFarPill = new GaiNearFarPillDistance();
        randPill = new GaiRandomPill();
        aSearch = new GaiAStarSearch();
        currentState = State.NEAR_PILL;
        needTarget = true;
    }

    public int action(GameStateInterface gs) {
    	
    	// choose the adjacent current with the
        // nearest pill
        // check that copying works!
        this.gs = gs.copy();
        current = gs.getPacman().current;

        updateState(currentState);
        
        //npd.score(gs, current);
        //Node target = npd.closest;
        /*if(needTarget){
        	randPill.score(gs, current);
        	target = randPill.randNode;
        	needTarget = false;
        }*/
       
        //Find best path to get the closest pill
        LinkedList<Node>  path = aSearch.findPath(current, target, gs);

        Node next = null;
        
        //Coloring the A* path
        //colorPath(path);
        
    	if(path.size() > 0) {
    		//System.out.println("path size: " + path.size());
    		next = path.getFirst();
    		
    		if(path.size() == 1) {
    			needTarget = true;
    		} 		
    	} else {
    		//Arrived at target!
    		needTarget = true;
    	}
        
        
        //Find Ghost distances
        /*for(GhostState ghost: gs.getGhosts()) {
        	int distance = gs.getMaze().dist(gs.getPacman().current, ghost.current);
        	System.out.println("Dist: " + distance);
        }*/
        
        //Node next = Utilities.getClosest(current.adj, npd.closest, gs.getMaze());
      //debug
        if(target == null) {
        	System.out.println("TARGET IS NULL");
        }
        if(next == null) {
        	//go anywhere
        	next = current.adj.get(0);
        	//System.out.println("NEXT IS NULL");
        }
        
        if(path == null) {
        	next = current.adj.get(0);
        }
        
        int dir = Utilities.getWrappedDirection(current, next, gs.getMaze());
        return dir;
    }
    
    public void updateState(State currState) {
    	
    	//Check if edible
    	int minGhostDist = Integer.MAX_VALUE;
    	Node ghostTarget = null;
    	for(GhostState ghostState : gs.getGhosts()) {
    		if(ghostState.edibleTime > 10) {
    			if(gs.getMaze().dist(current, ghostState.current) < minGhostDist) {
    				minGhostDist = gs.getMaze().dist(current, ghostState.current);
    				ghostTarget = ghostState.current;
    			}
    		}
    	}
    	if(ghostTarget != null) {
    		target = ghostTarget;
    		return;
    	}
    	//System.out.println("Edible: " + gs.getGhosts()[0].edibleTime);
    	
    	switch(currState) {
    	
    	case NEAR_PILL:
    		//check nearby ghost
    		if(nearGhost()) {
    			//needTarget = true;
    			changeState(State.RAND_PILL);
    			break;
    		}
    		if(needTarget) {
    			nearFarPill.score(gs, current);
    			target = nearFarPill.closest;
    			needTarget = false;
    		}
    		break;
    	
    	case RAND_PILL:
    		if(!nearGhost()) {
    			changeState(State.NEAR_PILL);
    			break;
    		}
    		if(needTarget){
            	randPill.score(gs, current);
            	target = randPill.randNode;
            	needTarget = false;
            }
    		break;
    		
    	}
    }
    
    public void changeState(State newState) {
    	needTarget = true;
    	currentState = newState;
    	updateState(currentState);
    }
    
    public boolean nearGhost() {
    	for(GhostState ghostState : gs.getGhosts()) {
    		if(gs.getMaze().dist(current, ghostState.current) < 15 ) {
    			//Ghost is nearby
    			return true;
    		}
    	}
    	return false;
    }
    
    public int dangerLevel() {
    	int dangerDistance = 10;
    	//TO DO
    	return 0;
    }
    
    public void colorPath(LinkedList<Node> path) {
    	if(path != null) {
        	for(Node n: path) {
        		if(n != target) {
        			n.col = Color.BLUE;
        		}	
        	}  	
        } else {
        	System.out.println("PATH IS NULL!!!");
        }
    }
    
    
}
